/*-*
 * FILENAME  :
 *    $HeadURL$
 *
 * STATUS  :
 *    $Revision$
 *
 *    $Author$
 *    $Date$
 *  
 *    
 * Copyright (c) 2011 Gonalge Ltda. All rights reserved.
 *
 ****************************************************************/

package org.gonalge.rompecabeza.remoto.imp;

import java.awt.List;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.gonalge.rompecabeza.dto.Jugador;
import org.gonalge.rompecabeza.dto.Mensaje;
import org.gonalge.rompecabeza.negocio.Juego;
import org.gonalge.rompecabeza.remoto.NotificadorRemoto;
import org.gonalge.rompecabeza.remoto.ServidorRemoto;

/**
 * 
 * @author Geremias Gonzalez
 */
public class Servidor extends UnicastRemoteObject implements ServidorRemoto {

    /**
     * 
     */
    private static final long serialVersionUID = -3245624059264385930L;

    private static final Log LOG = LogFactory.getLog(Servidor.class);

    private transient Vector<String> usuarios = new Vector<String>();

    private transient Vector<NotificadorRemoto> notificadores = new Vector<NotificadorRemoto>();

    private List lista = null;

    private Juego juego = null;

    public Servidor(List lista) throws RemoteException {
        this.lista = lista;
    }

    @Override
    public boolean conectar(String usuario, NotificadorRemoto notificador) throws RemoteException {
        if (exiteUsuario(usuario))
            return false;

        usuarios.add(usuario);
        lista.add(usuario);
        notificadores.add(notificador);

        try {
            notificador.conexionExitosa();
            if (juego != null) {
                enviarJuego(true, juego);
                juego.addJugador(new Jugador(usuario));
            }
            actualizarLista();
        } catch (RemoteException e) {
            LOG.error("conectar", e);
        }
        return true;
    }

    @Override
    public boolean desConectar(String Usuario) throws RemoteException {
        if (!exiteUsuario(Usuario))
            return false;
        eliminarUsuarioLista(Usuario);
        actualizarLista();
        return true;
    }

    @Override
    public void actualizarLista() throws RemoteException {
        for (int i = 0; i < usuarios.size(); i++) {
            try {
                notificadores.get(i).actualizarListaUsuarios(usuarios);
            } catch (RemoteException e) {
                e.getStackTrace();
            }
        }
    }

    /**************** otros metodo **************************/
    private boolean exiteUsuario(String Usuario) {
        return usuarios.contains(Usuario);
    }

    private void eliminarUsuarioLista(String usuario) {
        int n = buscarIndex(usuario);
        if (n != -1) {
            usuarios.remove(n);
            lista.remove(n);
            notificadores.remove(n);
            juego.getJugadores().remove(n);
            return;

        }
    }

    public void terminarServicio() {
        int n = usuarios.size();
        for (int i = 0; i < n; i++) {
            try {
                notificadores.get(i).terminarServicio();
            } catch (RemoteException e) {
                LOG.error("terminarServicio", e);
            }
        }

    }

    @Override
    public void enviarMensaje(Mensaje msm) {
        for (int i = 0; i < usuarios.size(); i++) {
            try {
                notificadores.get(i).enviarMensaje(msm);
            } catch (RemoteException e) {
                LOG.error("enviarMensaje", e);
            }
        }
    }

    @Override
    public void enviarJuego(boolean sw, Juego event) {
        this.juego = event;

        for (int i = 0; i < usuarios.size(); i++)
            juego.addJugador(new Jugador(usuarios.get(i)));

        for (int i = 0; i < usuarios.size(); i++) {
            try {
                notificadores.get(i).enviarJuego(sw, event);
            } catch (RemoteException e) {
                LOG.error("enviarJuego", e);
            }
        }
    }

    private int buscarIndex(String usuario) {
        for (int i = 0; i < usuarios.size(); i++) {
            String d = usuarios.get(i);
            if (d.equals(usuario))
                return i;

        }
        return -1;
    }

    @Override
    public void seleccionarPieza(String nick, int x, int y) {
        juego.selecionarPieza(nick, x, y);

    }

    @Override
    public void moverPieza(String nick, int x, int y) {
        juego.moverPieza(nick, x, y);
        for (int i = 0; i < usuarios.size(); i++) {
            try {
                notificadores.get(i).actualizarPiezas(juego.getPiezaPerdiente(), juego.getJugadores());
            } catch (RemoteException e) {
                LOG.error("moverPieza", e);
            }
        }
    }

    @Override
    public void soltarPieza(String nick) {
        juego.jugar(nick);

        for (int i = 0; i < usuarios.size(); i++) {
            try {
                notificadores.get(i).actualizarTablero(juego.getPiezaPerdiente(), juego.getJugadores(), juego.getEstadoTablero());
            } catch (RemoteException e) {
                LOG.error("soltarPieza", e);
            }
        }
    }
}
